home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 4 / United Public Domain Gold 4.iso / scope / sc093.dms / sc093.adf / VirusX / Source.LZH / virusx.c < prev    next >
Text File  |  1989-11-26  |  54KB  |  1,604 lines

  1. /************************************************************************/
  2. /*                                                                      */
  3. /*                                                                      */
  4. /*                                VirusX                                */
  5. /*                                                                      */
  6. /*                           by Steve Tibbett                           */
  7. /*                            and Dan James                             */
  8. /*                                                                      */
  9. /*              Please - if you find a new virus, Send me a copy!       */
  10. /*              (And warn me it's on the disk!).  I want to keep        */
  11. /*              this program current.  (Feel free to put something      */
  12. /*              neat on the disk also!)                                 */
  13. /*                                                                      */
  14. /*  The Makefile included in the "source.zoo" file you should have      */
  15. /*  gotten in the VirusX.Zoo file this came from, is set up for the     */
  16. /*  MANX Make Utility.  Switching to Lattice's LMK should be easy,      */
  17. /*  but I've had no reason to.  The important thing is the command      */
  18. /*  line switches and the BLINK command line.                           */
  19. /*                                                                      */
  20. /*  Thanks to John Toebes for a lot of help getting it going, and       */
  21. /*  thanks to Dan James for providing KV, and providing most of the     */
  22. /*  code that deals with the non-Bootblock viruses.                     */
  23. /*                                                                      */
  24. /************************************************************************/
  25. /*                                                                      */
  26. /*  History:                                                            */
  27. /*  --------                                                            */
  28. /*      April '88 or so:  V1.0 written and released.                    */
  29. /*     A few days later:  V1.01 released.  V1.0 wrote garbage to the    */
  30. /*                        disk if it was write protected then fixed.    */
  31. /*          27-March-88:  V1.2 released.  V1.2's purpose in life was    */
  32. /*                        to deal with the Byte Bandit virus.           */
  33. /*                        (Actually, it's well after midnight - make    */
  34. /*                        that March 28th. :)                           */
  35. /*          28-March-88:  Oops, V1.2 was 3K or so bigger than it needed */
  36. /*                        to be.  Fix it, release v1.21.                */
  37. /*           15-June-88:  V1.3, V1.2 cleaned up and made smaller.       */
  38. /*            8-July-88:  V1.4.  Revenge virus checking, Viewbooting,   */
  39. /*                        check for SCA in RAM, more cleaning up.       */
  40. /*           24-July-88:  V1.5, only change was the addition of the     */
  41. /*                        Byte Warrior virus.                           */
  42. /*             1-Aug-88:  V1.6 (busy week), Dan Mosedale sent me the    */
  43. /*                        Northstar Virus.  Nuked it.                   */
  44. /*            18-Aug-88:  V1.7 - after 2 weeks off, got the Obelisk     */
  45. /*                        Softworks crew virus.                         */
  46. /*     a few days later:  V1.71, can't remember why.                    */
  47. /*   September Sometime:  Biggest mistake of my life, released V2.0.    */
  48. /*         3 days later:  Bigger mistake:  Released V2.01 - which was   */
  49. /*                        2.0 with another bug added.  Argh.            */
  50. /*             6-Nov-88:  Finally got some time to clean things up,     */
  51. /*                        check out the startup code bugs, clean up the */
  52. /*                        docs and source, and release V2.1.  There     */
  53. /*                        haven't been any new viruses in about a month */
  54. /*                        now, but I hear one or two are on the way.    */
  55. /*            31-Dec-88:  Got the IRQ virus yesterday.  Neat one!       */
  56. /*                        Releasing V3.0 tonite or tomorrow to handle   */
  57. /*                        it.  See description below.                   */
  58. /*            04-Jan-89:  Got 2 new viruses, released 3.1.              */
  59. /*            18-Feb-89:  And boy, am I tired.  8 (count 'em) 8 new     */
  60. /*                        viruses in this version.  Ack!  DOUBLE        */
  61. /*                        the last version.  New option: CHECK, good    */
  62. /*                        for including VirusX with a commercial        */
  63. /*                        program.  V3.20                               */
  64. /*                                                                      */
  65. /*            26-Nov-89:  Has it been this long?  Anyways... I'm        */
  66. /*                        calling this one V4.0.  See the real docs     */
  67. /*                        for more information.                         */
  68. /*                                                                      */
  69. /************************************************************************/
  70. /*                                                                      */
  71. /*  Viruses Dealt With:                                                 */
  72. /*  -------------------                                                 */
  73. /*                                                                      */
  74. /*      SCA             - The SCA is the simplest virus to deal with,   */
  75. /*                        as it's not actually DOING anything except    */
  76. /*                        hiding in memory, until you reboot.           */
  77. /*                        We just look at CoolCapture and fix it to get */
  78. /*                        it out of RAM.                                */
  79. /*                                                                      */
  80. /*      Byte Bandit     - The Byte Bandit virus takes the DoIO() vector */
  81. /*                        and redirects it through itself.  Thus, any   */
  82. /*                        attempt to read or write the boot block (ie,  */
  83. /*                        AmigaDOS trying to figure out what kind of    */
  84. /*                        disk it is) results in the BB writing itself  */
  85. /*                        onto that disk.  VirusX couldn't just rewrite */
  86. /*                        the boot block, we have to get him out of RAM */
  87. /*                        first.  This virus also has an interrupt that */
  88. /*                        crashes the machine every 5 minutes or so     */
  89. /*                        after it's infected a few of your disks.  Ow. */
  90. /*                        It stays in memory not via the Capture        */
  91. /*                        vectors, but by a Resident module.            */
  92. /*                                                                      */
  93. /*      Revenge         - Basically, a Byte Bandit clone except it will */
  94. /*                        bring up an obscene pointer a few minutes     */
  95. /*                        after you reboot.  We treat it much like the  */
  96. /*                        byte bandit.                                  */
  97. /*                                                                      */
  98. /*      Byte Warrior    - Jumps right into 1.2 Kickstart.  Won't work   */
  99. /*                        under 1.3.  Hangs around via Resident struct, */
  100. /*                        doesn't do any damage.                        */
  101. /*                                                                      */
  102. /*      North Star      - Like SCA, hangs around via CoolCapture,       */
  103. /*                        killing CoolCapture kills the North Star.     */
  104. /*                                                                      */
  105. /*      Obelisk Softworks Crew                                          */
  106. /*                      - Hangs around via CoolCapture, also            */
  107. /*                        watches reads of DoIO() (but doesn't          */
  108. /*                        infect EVERY disk - onlyt ones you boot       */
  109. /*                        off of)                                       */
  110. /*                                                                      */
  111. /*       IRQ            - This is the FIRST Non-Bootblock Virus.        */
  112. /*                        It copies itself from place to place via the  */
  113. /*                        first executable program found in your        */
  114. /*                        startup-sequence.  It SetFunction's           */
  115. /*                        OldOpenLibrary(), has a KickTagPtr,           */
  116. /*                        and lives in the first hunk of an             */
  117. /*                        infected program.                             */
  118. /*                        THANKS! to Gary Duncan and Henrik Clausen for */
  119. /*                        being the first to send this one to me!       */
  120. /*                                                                      */
  121. /*  Pentagon Circle     - This one looks at the DoIO vector, and has    */
  122. /*                        a CoolCapture vector.  It will write itself   */
  123. /*                        over any virus inserted, but not onto         */
  124. /*                        anything else.  (Neat idea!).  No danger,     */
  125. /*                        easy to eliminate.  Holding left button       */
  126. /*                        while booting with this one shows different   */
  127. /*                        screen colour, but doesn't get rid of it.     */
  128. /*                        Thanks to Bill at CMI (CMI*BILL on Plink)     */
  129. /*                        for sending me this one!                      */
  130. /*                                                                      */
  131. /*  SystemZ Virus Protector                                             */
  132. /*                      - I took this one out.  It's not really a       */
  133. /*                        'Virus' in that it won't overwrite a disk     */
  134. /*                        without asking you first.  Besides, it seems  */
  135. /*                        a lot of people LIKE the SystemZ Virus        */
  136. /*                        Protector (though it isn't perfect).          */
  137. /*                                                                      */
  138. /*   Lamer Exterminator - THIS one was a bugger.  Yet another virus     */
  139. /*                        aimed at hurting people.  Y'see, a Lamer      */
  140. /*                        is apparently the worst kind of pirate -      */
  141. /*                        one who doesn't crack software, doesn't       */
  142. /*                        write software, just collects names and       */
  143. /*                        addresses and collects and spreads software.  */
  144. /*                        Lamers don't do anybody any good - and the    */
  145. /*                        guy behind this Virus took it upon himself    */
  146. /*                        to make their (and our) lives miserabler.     */
  147. /*                        Anyway, this virus loads into RAM into a      */
  148. /*                        different location every time (using a        */
  149. /*                        random location).  It is encrypted on the     */
  150. /*                        disk so you can't SEE the name of it, and     */
  151. /*                        it never actually SHOWS the name (but it's    */
  152. /*                        definately there).  It changes the            */
  153. /*                        encryption key used each time it is written   */
  154. /*                        back to disk.  It has a counter and will      */
  155. /*                        wait until the machine has been reset 2 times */
  156. /*                        OR until 3 disks have been infected, and will */
  157. /*                        then pick a DATA block (Only a DATA block -   */
  158. /*                        FFS disks are safe, I guess), randomly, and   */
  159. /*                        will write the word 'LAMER!' all through it.  */
  160. /*                        This is obviously not good, and will cause    */
  161. /*                        random disk errors.  This is the worst kind   */
  162. /*                        of havoc to wreak on the new user - and this  */
  163. /*                        virus is EVERYWHERE!  I've gotten it from 5   */
  164. /*                        people in the last week alone (all from       */
  165. /*                        different countries!  Ack!).  Anyways, credit */
  166. /*                        for being the first with this one is          */
  167. /*                        Christian Schneider.  Thanks, Christian!      */
  168. /*  Might as well break the margin convention here, eh?  Anyways,       */
  169. /*  something else I thought of about this virus:  It introduces a NEW  */
  170. /*  way for a Virus to stay in RAM.  Y'see, if ExecBase is okay at      */
  171. /*  reboot time (Exec keeps a checksum, among other things, and checks  */
  172. /*  to see if anything has been corrupted quite carefully).  Anyways,   */
  173. /*  if Exec thinks ExecBase is okay, it doesn't bother rebuilding it.   */
  174. /*  Sooo, this virus sets the SumKickData() vector to point at itself.  */
  175. /*  Then at Reboot when this vector gets called after reset, the virus  */
  176. /*  ReInstalls himself.  At least this is what I think is happening.    */
  177. /*  This virus sets up a Resident structure, but never sets the Match   */
  178. /*  Word - either this means we don't need the MatchWord or it means    */
  179. /*  his SumKickData() is doing the recovery job - either way, it's      */
  180. /*  new!  3 points for originality.                                     */
  181. /*                                                                      */
  182. /*  Graffiti - The first virus to come with rotating 3-d graphics!      */
  183. /*             It's neat - you might want to trigger it (I'm not sure   */
  184. /*             how) before nuking it.  Anyway, this one just sets       */
  185. /*             CoolCapture(), does something with DoIO() during the     */
  186. /*             reboot but sets it back to normal before anybody gets    */
  187. /*             to look at it.  Lots of code is taken by the graphics    */
  188. /*             stuff.  I just clear the CoolCapture vector.  [yawn]     */
  189. /*                                                                      */
  190. /*  Old Northstar - Poof.                        */
  191. /*                                                                      */
  192. /*  16 Bit Crew - Well, I didn't actually have to DO anything to get    */
  193. /*         VirusX to recognize it... because it seems to operate  */
  194. /*               like the Graffiti Virus.  If the 16 bit crew is in     */
  195. /*               RAM, VirusX will say it removed the Graffiti virus.    */
  196. /*               Oh well.  8-)                                          */
  197. /*                                                                      */
  198. /*  DiskDoktor - I spent more time on this one than on any other.       */
  199. /*               Y'see, this virus does lots of things.  The first one  */
  200. /*               for some reason was quite funny to me.  heh            */
  201. /*               What it would do is after you have rebooted 5 times,   */
  202. /*               each time you reboot after that, the virus would eat   */
  203. /*               10K times the total number of reboots - so after       */
  204. /*               rebooting 10 times, you would be short about 100K.     */
  205. /*               This virus also starts up another TASK.  I'm not       */
  206. /*               exactly sure when it happens, but another task named   */
  207. /*               'clipboard.device' will appear at a priority of -120,  */
  208. /*               and will continually bash the Virus' vectors into the  */
  209. /*               Coldcapture, Coolcapture, Warmcapture (which it sets   */
  210. /*               to $ff000000 just to annoy), and the DoIO() vector.    */
  211. /*               When I was working on this one, I figured I just had   */
  212. /*               to restore the old values to the DoIO() vector, but as */
  213. /*               soon as I did so, the Virus restored them - and since  */
  214. /*               I didn't disassemble the entire thing, I didn't realize*/
  215. /*               this until I wasted time looking for other faults.     */
  216. /*               This one also allocates some memory, copies some code  */
  217. /*               out of Exec into this memory, and executes it.  I      */
  218. /*               never bothered to figure out why - Once it's gone, it's*/
  219. /*               gone.                                                  */
  220. /*                                                                      */
  221. /*  Australian Parasite:  Hey - I like this one.  It says it will       */
  222. /*   not destroy game bootsectors or corrupt disks - but it's still a   */
  223. /*   Virus.  What makes this one unique is the way it lets itself       */
  224. /*   be known.  Get this - after so many disk accesses (something like  */
  225. /*   600 blocks read off of a floppy), it turns your screen Upside Down!*/
  226. /*   Nifty.  You can still USE the screen upside down - it just looks,  */
  227. /*   well, a bit weird.  Anyway, it uses the DoIO() vector, the TD      */
  228. /*   Read vector, starts at SysStkLower, and that's about it.  Stays    */
  229. /*   around via CoolCapture.  Thanks to Martyn at 17Bit Software        */
  230. /*   in England for being the first to send this to me.                 */
  231. /*                                                                     */
  232. /*   VKill:  This one doesn't think it's a virus, and depending on    */
  233. /*   your point of view, it might not be.  It won't write itself to   */
  234. /*  a nonstandard boot block - so it won't hurt games.  But it will   */
  235. /*     still load into your system, vector your PutMsg() routine      */
  236. /*   through itself, sit on your supervisor stack, without telling    */
  237. /*    you.  Not good.  I have had this one for a while, trying to     */
  238. /*    decide what to do with it - I guess what convinced me is the    */
  239. /*   fact that the text message which identifies itself is actually   */
  240. /*   ENCRYPTED - for a virus killer, this is a pretty questionable    */
  241. /*                            thing to do.                            */
  242. /*                                                                     */
  243. /************************************************************************/
  244. /*                                                                      */
  245. /*  Thanks also to Robb Walton for being the first to send one of the   */
  246. /*  other ones, (but I can't remember which one anymore... 8-(  )       */
  247. /*                                                                      */
  248. /************************************************************************/
  249.  
  250. #include "virusx.h"
  251. #include "virusx.i"
  252.  
  253. void MemCleanup() {}
  254. extern struct DOSBase *DOSBase;
  255.  
  256. void 
  257. chkabort(void) {}
  258.  
  259. int ReadBlock(int block, APTR loc);
  260.  
  261. #define BREAK (SetSignal(0,0) & SIGBREAKF_CTRL_C)
  262.  
  263. /******************************************************************/
  264. /* These string constants are used in multiple places, and thus   */
  265. /* save bytes by having only one copy of them.                    */
  266. /******************************************************************/
  267. char TITLETEXT[]        = "VirusX 4.00 by Steve Tibbett";
  268. char CHECKINGTEXT[]    = "VirusX: Checking Device DF0:";
  269. char TDName[]           =  "trackdisk.device";
  270. char ITBodyText[80];
  271. char text[]             = "DF?: Boot Sectors";
  272.  
  273. char BGSCheck[]        = { 'D','E','V','S','/',0xa0,0xa0,0xa0,0x20,0x20,0x20,0xa0,0x20,0x20,0x20,0xa0,0x00 };
  274.  
  275. /**********************************************************************/
  276. /*                            The Big One                             */
  277. /**********************************************************************/
  278. extern struct VirusInfo VI[];
  279.  
  280. /************************************************************************/
  281. /*  Miscellaneous variables.                                            */
  282. /************************************************************************/
  283. long    ChangeCount[4];                 /* TD_CHANGECOUNT for 4 drives  */
  284. long    LastSum;                        /* Used in the checksumming     */
  285. long    error;                          /* sort of a temporary variable */
  286. char    WindowBig = FALSE;              /* TRUE if the window is big    */
  287. int     VirusesInBigWindow;        /* For setting big window size  */
  288. struct  Port *diskport;                 /* trackdisk's port.            */
  289. struct  IOStdReq *diskreq;              /* trackdisk's IOStdReq         */
  290. long    DisksChecked, DisksInstalled;   /* for title bar info           */
  291. struct     Process *Me;            /* for setting the WindowPtr    */
  292. int     WindowYDelta;            /* Big Window Y Size Change    */
  293.  
  294.  
  295. char     CaptureCheck = TRUE;
  296. char     KickTagCheck = FALSE;
  297. char    CheckAndQuit = FALSE;
  298. char    SetPatchFlag = FALSE;
  299.  
  300. struct IntuitionBase    *IntuitionBase;     /* For Library Bindings */
  301. struct GfxBase          *GfxBase;
  302. struct Window           *Window;
  303. struct IntuiMessage     *Message;
  304. struct ExecBase         *ExecBase;
  305. struct Screen        *Screen;
  306.  
  307. char Keepgoing;         /* A flag.  It's false when we want out.        */
  308. long x, y, i;           /* Left over from my using Basic                */
  309. char flag;              /* Another flag.  Lets start our own country.   */
  310.  
  311. void RenderItem(char *Item, int Value);
  312.  
  313. struct NewWindow NewWindow =
  314.         {
  315.         128,0,  309,10,  0,1,
  316.         DISKINSERTED | CLOSEWINDOW | VANILLAKEY | NEWSIZE | MOUSEBUTTONS, /* IDCMP Flagz */
  317.         WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */
  318.         NULL, NULL,TITLETEXT,
  319.         NULL,NULL,0,0,0,0,WBENCHSCREEN,
  320.         };
  321.  
  322. struct RastPort *RP;
  323. unsigned char *diskbuffer;
  324.  
  325. /************************************************************************/
  326. /* Warning messages.  These messages get modified before being          */
  327. /* displayed (Unless you DO have a DF9:)                                */
  328. /************************************************************************/
  329. char TEXTPTR[] = "Danger:  The disk in DF?: is";
  330. char NBCTEXT[] = "Danger:  The disk in DF?: has";
  331.  
  332. /*************************************************************************/
  333. /*   This is a byte by byte copy of working boot block code.  Check it   */
  334. /*   out if you like.  This is what gets written back to the disk when   */
  335. /*   you ask VirusX to fix a disk.                                       */
  336. /*************************************************************************/
  337. unsigned char bootblock[] = { 'D', 'O', 'S', 0,
  338. 0xc0, 0x20, 0x0f, 0x19, 0x00, 0x00, 0x03, 0x70, 0x43, 0xfa, 0x00, 0x18,
  339. 0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68,
  340. 0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64, 0x6f,
  341. 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
  342. 0x00, 0x00};
  343.  
  344. /**********************************************************************/
  345. /*                         It all starts here                         */
  346. /**********************************************************************/
  347. int
  348. main(int argc, char **argv)
  349. {
  350. x=1;
  351.  
  352. while (argv[x] != 0)
  353.     {
  354.     if (argv[x][0] == '-')
  355.         {
  356.         switch (toupper(argv[x][1]))
  357.             {
  358.             case 'A':
  359.                 NewWindow.Flags |= ACTIVATE;
  360.                 break;
  361.             case 'C':
  362.                 CaptureCheck = FALSE;
  363.                 break;
  364.             case 'K':
  365.                 KickTagCheck = TRUE;
  366.                 break;
  367.             case 'Q':
  368.                 CheckAndQuit = TRUE;
  369.                 break;
  370.             case 'R':
  371.                 SetPatchFlag = TRUE;
  372.                 break;
  373.             case 'X':
  374.                 NewWindow.LeftEdge = atoi(&argv[x][2]);
  375.                 break;
  376.             case 'Y':
  377.                 NewWindow.TopEdge = atoi(&argv[x][2]);
  378.                 break;
  379.             };
  380.         };
  381.     x++;
  382.     };
  383.  
  384. if  ((diskbuffer = AllocMem((long)1024, (long)MEMF_CHIP|MEMF_CLEAR)) == 0) 
  385.     goto OuttaHere;
  386.  
  387. /* These had better not ever fail.  If they do, something's Very wrong. */
  388. IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L);
  389. GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
  390. ExecBase = (struct ExecBase *)OpenLibrary("exec.library", 0L);
  391.  
  392. Me = (struct Process *)FindTask(0L);
  393. Me->pr_WindowPtr = 0;
  394.  
  395. /*  We use the same port/request through the whole program.  Works OK. */
  396. diskport = CreatePort(0L,0L);
  397. diskreq = CreateStdIO(diskport);
  398.  
  399. if ((Window = OpenWindow(&NewWindow)) == NULL)
  400.     goto Quitter;
  401.  
  402. RP = Window->RPort;
  403. Screen = Window->WScreen;
  404.  
  405. /* Set the ChangeCount for the Trackdisk devices */
  406. SetUp();
  407.  
  408. /* Check RAM out... */
  409. CheckMemoryForViruses();
  410. CheckMemoryForLinkViruses();
  411.  
  412. CheckBlock();
  413.  
  414. if (!CheckAndQuit)
  415.     DoLittle();
  416.  
  417. Quitter:
  418. if (Window != 0) CloseWindow(Window);
  419. if (diskport != 0) DeletePort(diskport);
  420. if (diskreq != 0) DeleteStdIO(diskreq);
  421. FreeMem(diskbuffer, (long)1024 );
  422. OuttaHere:
  423. CloseLibrary(GfxBase);
  424. CloseLibrary(IntuitionBase);
  425. CloseLibrary((struct Library *)ExecBase);
  426. return(0);
  427. }
  428.  
  429. /**********************************************************************/
  430. /*                   This is the main VirusX loop.                    */
  431. /**********************************************************************/
  432. void
  433. DoLittle(void)
  434. {
  435. long Code, Class;     /* for storing our IntuiMessage stuff */
  436. char KG2;              /* KeepGoing 2.  Another boolleean. */
  437. int phase;
  438.  
  439. KG2 = TRUE;
  440.  
  441. SetAPen(RP, 1L);
  442. SetBPen(RP, 0L);
  443. SetDrMd(RP, (long)JAM2);
  444.  
  445. phase = 0;
  446.  
  447. while (KG2 == TRUE)
  448.         {
  449.     if (BREAK) break;
  450.  
  451.     Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
  452.         if (Message == 0)
  453.                    {
  454.                    WaitTOF();
  455.                 WaitTOF();
  456.                    WaitTOF();    /* I don't trust Delay() anymore */
  457.                 WaitTOF();
  458.                    WaitTOF();
  459.                    WaitTOF();
  460.  
  461.         if (++phase > 20) 
  462.             {
  463.             phase = 0;
  464.             CheckMemoryForLinkViruses();
  465.             };
  466.                 continue;
  467.                 };
  468.  
  469.         Class = Message->Class;
  470.         Code = Message->Code;
  471.         ReplyMsg((struct Message *)Message);
  472.  
  473.         switch (Class)
  474.         {
  475.         case CLOSEWINDOW:
  476.                     KG2 = FALSE;
  477.                 break;
  478.         
  479.         case MOUSEBUTTONS:
  480.             if (Code == MENUDOWN)
  481.                 ToggleBigWindow();
  482.             break;
  483.  
  484.         case VANILLAKEY:
  485.             switch (toupper(Code))
  486.                             {
  487.                             case 'I':
  488.                                     ToggleBigWindow();
  489.                                     break;
  490.                 case 'C':
  491.                                     for (x=0; x<4; x++) ChangeCount[x] = 10000;
  492.                                     CheckBlock();
  493.                     break;
  494.                 case 27:
  495.                     KG2 = FALSE;
  496.                     break;
  497.                 default:
  498.                                     flag = ShowAscii(Code);
  499.                                     if (flag == 1) CheckBlock();
  500.                             };
  501.                     break;
  502.  
  503.         case DISKINSERTED:
  504.                     CheckBlock();
  505.                 break;
  506.  
  507.             };
  508.  
  509.         if (WindowBig) RenderInfo();
  510.         };
  511. }
  512.  
  513.  
  514. /************************************************/
  515. /* Opens trackdisk, finds out who's out there,  */
  516. /* and sets Changecount up accordioningly.      */
  517. /************************************************/
  518. void
  519. SetUp(void)
  520. {
  521. long x;
  522.  
  523. for (x = 0; x < 4; x++) /* go thru all 4 possible drives */
  524.         {
  525.         ChangeCount[x] = 1000;
  526.         error = OpenDevice(TDName,(long)x,diskreq,0L);
  527.         if (error > 0)
  528.                 ChangeCount[x] = -1;
  529.         else CloseDevice(diskreq);
  530.         };
  531. }
  532.  
  533. /*********************************************************/
  534. /* This routine returns which drive changed disks lately */
  535. /*********************************************************/
  536. int
  537. WhoChanged(void)
  538. {
  539. int RetVal = -1;       /* The value we'll return */
  540.  
  541. for (x = 0; x < 4; x++)
  542.         {
  543.         if (ChangeCount[x] == -1)
  544.                 continue;       /* no drive here */
  545.  
  546.         error = OpenDevice(TDName,(long)x,diskreq,(long)0);
  547.         if (error > 0)
  548.                 continue;       /* no drive here */
  549.  
  550.         diskreq->io_Command = TD_CHANGESTATE;
  551.         DoIO(diskreq);
  552.         if (diskreq->io_Actual != 0)
  553.                 {
  554.                 CloseDevice(diskreq);
  555.                 continue;
  556.                 };
  557.  
  558.         diskreq->io_Command = TD_CHANGENUM;
  559.         DoIO(diskreq);
  560.         if (diskreq->io_Actual != ChangeCount[x])
  561.                 {
  562.                 RetVal = x;
  563.                 ChangeCount[x] = diskreq->io_Actual;
  564.                 CloseDevice(diskreq);
  565.                 break;
  566.                 };
  567.  
  568.         CloseDevice(diskreq);
  569.         };
  570.  
  571. return(RetVal);
  572. }
  573.  
  574. /****************************************************************/
  575. /*  Figures out which drive changed disks (using WhoChanged(),  */
  576. /*  And checks it.  Calling this after every DISKINSERTED is OK.*/
  577. /****************************************************************/
  578. void
  579. CheckBlock(void)
  580. {
  581. long Sum, a, Unit;
  582. unsigned long *iptr, *ptr;
  583. char drivename[10];
  584.  
  585. while ((Unit = WhoChanged()) != -1)
  586.         {
  587.     short VirusFound = -1, x = 0, Virus = FALSE;
  588.  
  589.      CHECKINGTEXT[26] = '0'+Unit;
  590.     SetWindowTitles(Window, CHECKINGTEXT, (STRPTR)-1);
  591.         strcpy(drivename, "DF0:");
  592.         drivename[2] = '0'+Unit;
  593.  
  594.         /* Unit # to open is returned by "WhoChanged()" up above. */
  595.         if (Unit == -1) continue;
  596.  
  597.         error = OpenDevice(TDName,(long)Unit,diskreq,0L);
  598.         if (error > 0) continue;
  599.     error = ReadBootBlock();
  600.         DisksChecked++;
  601.         CloseDevice(diskreq);
  602.         if (error == FALSE) continue;
  603.  
  604.         ptr = (long *)diskbuffer;
  605.         iptr = (long *)diskbuffer;
  606.  
  607.         if (iptr[0] != ID_DOS_DISK) 
  608.         continue;
  609.     
  610.         Sum = 0;
  611.         for (a=0; a<256; a++)
  612.                 {
  613.                 LastSum = Sum;
  614.                 Sum = Sum + ptr[a];
  615.                 if (LastSum > Sum) Sum++;  /* took me a while to figger this out */
  616.                 }
  617.  
  618.         if (Sum != 0)
  619.                 {
  620.         CheckDriveForLinkViruses(drivename);
  621.                 continue; /* if it's not bootable, we DONT want it! */
  622.                 };
  623.  
  624.     while (VI[x].Name != 0)
  625.         {
  626.         if (Virus == TRUE) break;
  627.  
  628.         if (iptr[VI[x].LongWordOffsets[0]] == VI[x].WhatToExpect[0])
  629.             if (iptr[VI[x].LongWordOffsets[1]] == VI[x].WhatToExpect[1])
  630.                 {
  631.                 VI[x].NumFound++;
  632.                 VirusFound = x;
  633.                 Virus = TRUE;
  634.                 break;
  635.                 };
  636.         x++;
  637.         };
  638.  
  639.         /* compare boot block with real boot block.  If it's not, notify */
  640.         if (Virus == FALSE)
  641.             for (x = 0; x < 39; x++) /* num of bytes in bootblock */
  642.                     if (diskbuffer[8+x] != bootblock[8+x])
  643.                             Virus = TRUE;
  644.  
  645.     /* Oh no, a Virus! */
  646.         if (Virus == TRUE)
  647.                 {
  648.                 NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */
  649.                 TEXTPTR[23] = '0'+Unit;
  650.                 error = FALSE;
  651.  
  652.                 /* Should check Copy Count flag sometime... */
  653.         if (VirusFound != -1)
  654.             error = MyRequest(VI[VirusFound].Name, 1);
  655.             else
  656.                         {
  657.                         /* Probably just a custom boot block (or a new virus...) */
  658.             char buf[200];
  659.             strcpy(buf, NBCTEXT);
  660.             strcat(buf, "|Nonstandard Boot Code!");
  661.             WBenchToFront();
  662.             error = SimpleRequest(buf, "Ignore It|Repair It", Window, 0);
  663.                         }
  664.  
  665.                 if (error != 0) 
  666.             DoInstall(Unit); /* user wants it neutered. */
  667.                 };
  668.  
  669.         CheckDriveForLinkViruses(drivename);
  670.         };  /* End of While Whochanged */
  671.  
  672. SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
  673. }
  674.  
  675. /********************************************/
  676. /* This is where the boot code gets changed */
  677. /********************************************/
  678. void  
  679. DoInstall(int un)
  680. {
  681. int x;
  682.  
  683. /* Rewrite disk?  Really?  */
  684. error = SimpleRequest("Install New Bootblock?|Are you sure?", "No, Cancel|Yes, Do It", Window, 0);
  685.  
  686. if (error == 0) return;      /* user changed his brain. */
  687.  
  688. DisksInstalled++;
  689.  
  690. error = OpenDevice(TDName, (long)un,diskreq,0L);
  691. if (error > 0) return;
  692.  
  693. while (ProtStatus() == TRUE)
  694.         {
  695.     error = SimpleRequest("The disk is write protected.", "Forget It|Try Again", Window, 0);
  696.         if (error != 0) /* error is true or false, depending on user */
  697.         continue;
  698.         CloseDevice((struct IOStdReq *)diskreq);
  699.         return; /* unrecoverable write protect error!! Panic!!!!!!! */
  700.     };
  701.  
  702. for (x = 0; x < 1024; x++)
  703.         diskbuffer[x] = 0;      /* clear diskbuffer to zero.  clean. */
  704.  
  705. CopyMem(bootblock, diskbuffer, 50L); /* Copy it over */
  706.  
  707. /* Write it ! */
  708.  
  709.         error = 0;
  710.         diskreq->io_Length = 1024; /* here we go! */
  711.         diskreq->io_Data = (APTR)diskbuffer;
  712.         diskreq->io_Command = CMD_WRITE;
  713.         diskreq->io_Offset = 0L;
  714.         DoIO((struct IOStdReq *)diskreq);
  715.         error = diskreq->io_Error;
  716.  
  717. if (error < 19 && error != 29)
  718.         {
  719.         diskreq->io_Command = CMD_UPDATE;       /* flush buffer to disk */
  720.         DoIO((struct IOStdReq *)diskreq);
  721.         error = diskreq->io_Error;
  722.         };
  723.  
  724. MotorOff();
  725.  
  726. if (error > 19 && error != 29)
  727.     SetWindowTitles(Window, "Disk Error!", (STRPTR)-1);
  728.     else SetWindowTitles(Window, "Disk Healed.", (STRPTR)-1);
  729.  
  730. Delay(75L);
  731. SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
  732.  
  733. CloseDevice((struct IOStdReq *)diskreq);
  734. }
  735.  
  736.  
  737. /**********************************************************************/
  738. /*                      Turn off the Disk Motor                       */
  739. /**********************************************************************/
  740. void
  741. MotorOff(void)
  742. {
  743.     diskreq->io_Length = 0;
  744.     diskreq->io_Command = TD_MOTOR;/* Motor Off */
  745.     DoIO(diskreq);
  746. }
  747.  
  748. /* This has to be global */
  749. unsigned long *TD;
  750.  
  751. /**********************************************************************/
  752. /*             Check RAM for Known Viruses from Database              */
  753. /**********************************************************************/
  754. void
  755. CheckMemoryForViruses(void)
  756. {
  757. short x = 0, y;
  758. short LookFlags;
  759. char AlertFlag;
  760. unsigned long *EB;
  761.  
  762. EB = (unsigned long *)ExecBase;
  763. TD = (unsigned long *)FindName(&ExecBase->DeviceList, "trackdisk.device");
  764.  
  765. while (VI[x].Name != 0)
  766.     {
  767.     AlertFlag = FALSE;
  768.     
  769. /* * * Check First * * */
  770.  
  771.     if (VI[x].Handler != 0)
  772.         AlertFlag = ((VI[x].Handler)());
  773.     else
  774.     for (y=0; y<2; y++)
  775.         {
  776.         LookFlags = VI[x].HowToLook[y]; 
  777.         if (LookFlags == 0) continue;
  778.     
  779.         if (LookFlags & HTL_TDM1C)
  780.             {
  781.             unsigned long *TTD = TD;
  782.             
  783.             TTD = TTD - (0x1c / 4);
  784.  
  785.             if (LookFlags & HTL_LOOKINDIRECT) TTD = (unsigned long *)*TTD;
  786.  
  787.             TTD = (char *)(((unsigned long)TTD)+VI[x].LookOffset[y]);
  788.  
  789.             if (*TTD == VI[x].WhatToLookFor[y]) 
  790.                 { AlertFlag = TRUE; }
  791.                 else AlertFlag = FALSE;
  792.             };
  793.  
  794.         if (LookFlags & HTL_DOIO)
  795.             {
  796.             unsigned long *TEB;
  797.  
  798.             TEB = (char *)(((unsigned long)EB)-0x1c6);
  799.     
  800.             if (LookFlags & HTL_LOOKINDIRECT) TEB = (unsigned long *)*TEB;
  801.  
  802.             TEB = (char *)(((unsigned long)TEB)+VI[x].LookOffset[y]);
  803.         
  804.             if (*TEB == VI[x].WhatToLookFor[y]) 
  805.                 { AlertFlag = TRUE; }
  806.                 else AlertFlag = FALSE;
  807.             };
  808.  
  809.         if (LookFlags & HTL_ABSOLUTE)
  810.             {
  811.             unsigned short *S;
  812.  
  813.             S = VI[x].WhatToLookFor[y];
  814.             if (*S == VI[x].LookOffset[y])
  815.                 AlertFlag = TRUE;
  816.             };
  817.  
  818.  
  819. /* * * DONE CHECKING, NOW FIX * * */
  820.  
  821.         if (AlertFlag == TRUE)
  822.             {
  823.             for (y=0; y<2; y++)
  824.                 {
  825.                 unsigned long *Dest;
  826.  
  827.                 LookFlags = VI[x].DoToThis[y]; 
  828.                 if (LookFlags == 0) continue;
  829.  
  830.                 if (LookFlags & HTL_CLEARKICKTAGS)
  831.                     ExecBase->KickTagPtr = 0;
  832.  
  833.                 if (LookFlags & HTL_SETLONG)
  834.                     {
  835.                     unsigned long *ptr;
  836.                     ptr = VI[x].WhatToLookFor[0];
  837.                     *ptr = VI[x].WhatToLookFor[1];
  838.                     };
  839.     
  840.                 if (LookFlags & HTL_TDM1C)
  841.                     {
  842.                     unsigned char *t;
  843.                     unsigned long *TEB;
  844.         
  845.                     t = (unsigned char *)TD;
  846.                     t = t - 0x1c;
  847.                     TEB = (unsigned long *)t;
  848.  
  849.                     Dest = TEB;
  850.  
  851.                     TEB = (unsigned long *)*TEB;
  852.  
  853.                     t = (char *)TEB;
  854.                     t = t + VI[x].AtOffset[y];
  855.                     TEB = (unsigned long *)t;
  856.         
  857.                     Forbid();
  858.                     if (LookFlags & HTL_SETTO)
  859.                         {
  860.                         *TEB = VI[x].WithThis[y];
  861.                         }
  862.                         else Dest[0] = *TEB;
  863.                     Permit();
  864.                     };
  865.  
  866.  
  867.                 if (LookFlags & HTL_DOIO)
  868.                     {
  869.                     unsigned char *t;
  870.                     unsigned long *TEB;
  871.  
  872.                     t = (unsigned char *)EB;
  873.                     t = t - 0x1c6;
  874.                     TEB = (unsigned long *)t;
  875.  
  876.                     Dest = TEB;
  877.  
  878.                     TEB = (unsigned long *)*TEB;
  879.  
  880.                     t = (char *)TEB;
  881.                     t = t + VI[x].AtOffset[y];
  882.                     TEB = (unsigned long *)t;
  883.  
  884.                     Forbid();
  885.                     if (LookFlags & HTL_SETTO)
  886.                         *TEB = VI[x].WithThis[y];
  887.                         else
  888.                         {
  889.                         Dest[0] = *TEB;
  890.                         };
  891.                         
  892.                     Permit();
  893.                     };
  894.                 };
  895.             };
  896.         };
  897.  
  898.     /* Do this AFTER processing the REAL removal. */
  899.  
  900.     if (VI[x].CoolCapture != 0)
  901.         {
  902.         if ((long *)ExecBase->CoolCapture == (long *)VI[x].CoolCapture)
  903.             {
  904.             ExecBase->CoolCapture = 0;
  905.             AlertFlag = TRUE;
  906.             };
  907.         };
  908.  
  909.         if (AlertFlag == TRUE) 
  910.         {
  911.         MyRequest(VI[x].Name, 2);
  912.         };
  913.     x++;
  914.     }
  915.  
  916. if ((ExecBase->CoolCapture != NULL) && CaptureCheck)
  917.     {
  918.     if (SetPatchFlag)
  919.         if ((ExecBase->CoolCapture>(APTR)0x80000) && (ExecBase->CoolCapture<(APTR)0x100000))
  920.             goto SkipCoolCapCheck;
  921.     x = SimpleRequest("The system's CoolCapture Vector|is not Zero.  This could mean a new|Virus is in RAM, or that some other program|is using this vector.  See the|VirusX Documentation for more info.|Clear it?", " Yes | No ", Window, 0);
  922.     if (x == 0) ExecBase->CoolCapture = NULL;
  923.     };
  924.  
  925. if ((ExecBase->ColdCapture != NULL) && CaptureCheck)
  926.     {
  927.     if (SetPatchFlag)
  928.         if ((ExecBase->ColdCapture>(APTR)0x80000) && (ExecBase->ColdCapture<(APTR)0x100000))
  929.             goto SkipCoolCapCheck;
  930.     x = SimpleRequest("The system's ColdCapture Vector|is not Zero.  This could mean a new|Virus is in RAM, or that some other program|is using this vector.  See the|VirusX Documentation for more info.|Clear it?", " Yes | No ", Window, 0);
  931.     if (x == 0) ExecBase->ColdCapture = NULL;
  932.     };
  933.  
  934. SkipCoolCapCheck:
  935. if ((ExecBase->KickTagPtr != NULL) && (KickTagCheck == TRUE))
  936.     {
  937.     x = SimpleRequest("The system's KickTagPtr Vector|is not Zero.  This could mean a new|Virus is in RAM, or that some other program|is using this vector.  See the|VirusX Documentation for more info.|Clear it?", " Yes | No ", Window, 0);
  938.     if (x == 0) ExecBase->KickTagPtr = NULL;
  939.     };
  940.  
  941. }
  942.  
  943. /**************************************************************/
  944. /*  This is the routine that displauys a block as ASCII text. */
  945. /**************************************************************/
  946. int 
  947. ShowAscii(long key)
  948. {
  949. int drive, x, y, deltax, deltay;
  950. long a;
  951. int FLAG=0;
  952.  
  953. drive = key - '0';
  954.  
  955. if ((drive < 0) || (drive > 3) || (ChangeCount[drive] == -1)) return(0);
  956.  
  957. if ((error = OpenDevice(TDName,(long)drive,diskreq,0L)) > 0) return(0);
  958. error = ReadBootBlock();
  959. CloseDevice(diskreq);
  960. if (error == FALSE) return(0);
  961.  
  962. /* save the amount we moved the window */
  963. deltax = Window->LeftEdge;
  964. deltay = Window->TopEdge;
  965.  
  966. WindowToFront(Window);
  967. MoveWindow(Window, -deltax, -deltay);
  968. SizeWindow(Window, 278L, 160-WindowYDelta);
  969. WaitForNewSize();
  970.  
  971.  
  972. SetAPen(RP, 0L);
  973. RectFill(RP, 2, 12, 278, 167);
  974.  
  975. SetAPen(RP, 3L);
  976. Move(RP, (long)(14+(12*8)), 165L);
  977. Text(RP, "Block 0", 7L);
  978. Move(RP, (long)(324+(12*8)), 165L);
  979. Text(RP, "Block 1", 7L);
  980. SetAPen(RP, 1L);
  981.  
  982. text[2] = key;
  983. SetWindowTitles(Window, text, (STRPTR)-1);
  984.  
  985. x=0; y=0;
  986.  
  987. SetAPen(RP, 1L);
  988. SetDrMd(RP, JAM2);
  989.  
  990. for (a=0; a<512; a=a+32)
  991.         {
  992.         Move(RP, (long)(10+(x*8)), (long)20+(y*9));
  993.         Text(RP, &diskbuffer[a], 32L);
  994.  
  995.         Move(RP, (long)(320+(x*8)), (long)20+(y*9));
  996.         Text(RP, &diskbuffer[a+512], 32L);
  997.         y++;
  998.         };
  999.  
  1000. Wait(1<<Window->UserPort->mp_SigBit);
  1001. Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
  1002.  
  1003. /*  If a disk was inserted, we want CheckBlock() to happen later on some time */
  1004. if (Message->Class == DISKINSERTED) FLAG=1;
  1005. ReplyMsg((struct Message *)Message);
  1006.  
  1007. SetAPen(RP, 0L);
  1008. RectFill(RP, 2, 12, 278, 167);
  1009.  
  1010. SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
  1011.  
  1012. SizeWindow(Window, -278L, -160+WindowYDelta);
  1013. WaitForNewSize();
  1014. if (WindowBig) RenderInfo();
  1015.  
  1016. /* deltas plus current position, in case dude moved the window */
  1017. MoveWindow(Window, deltax+(-Window->LeftEdge), deltay+(-Window->TopEdge));
  1018. Delay(10L);
  1019.  
  1020. return(FLAG);
  1021. }
  1022.  
  1023.  
  1024. /**********************************************************************/
  1025. /* When you do a SizeWindow() command, you have to wait for a NEWSIZE */
  1026. /* IntuiMessage before drawing in it.  That's all this routine does.  */
  1027. /**********************************************************************/
  1028. void
  1029. WaitForNewSize(void)
  1030. {
  1031. int Class;
  1032.  
  1033. while (TRUE)
  1034.     {
  1035.     WaitPort(Window->UserPort);
  1036.     Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
  1037.     Class = Message->Class;
  1038.     ReplyMsg((struct Message *)Message);
  1039.     if (Class != MOUSEBUTTONS) break;
  1040.     };
  1041. }
  1042.  
  1043.  
  1044. /**********************************************************************/
  1045. /*                        Make an AutoRequest.                        */
  1046. /*                                                                    */
  1047. /*                               Types:                               */
  1048. /*                                                                    */
  1049. /*                1: "is infected with the xxx VIRUS!"                */
  1050. /*            2: "NOTICE:  The `blah' VIRUS was found..."             */
  1051. /*                      3: Cold/capture warning.                      */
  1052. /**********************************************************************/
  1053. int
  1054. MyRequest(char *string, int type)
  1055. {
  1056. char buf[255];
  1057.  
  1058. switch (type)
  1059.         {
  1060.         case 1:
  1061.                 strcpy(ITBodyText, "infected with the `");
  1062.                 strcat(ITBodyText, string);
  1063.                 strcat(ITBodyText, "' VIRUS!");
  1064.                 break;
  1065.         case 2:
  1066.                 strcpy(ITBodyText, "NOTICE:  The `");
  1067.                 strcat(ITBodyText, string);
  1068.                 strcat(ITBodyText, "' VIRUS was found");
  1069.                 break;
  1070.         };
  1071.  
  1072.  
  1073. WBenchToFront();
  1074. switch (type)
  1075.     {
  1076.     case 1:
  1077.         strcpy(buf, TEXTPTR);
  1078.         strcat(buf, "|");
  1079.         strcat(buf, ITBodyText);
  1080.         return(SimpleRequest(buf, "Ignore It|Repair It", Window, 0));
  1081.     case 2:
  1082.         strcpy(buf, "NOTICE:|The ");
  1083.         strcat(buf, string);
  1084.         strcat(buf, " VIRUS was found|in memory, and is now Disabled.|Please see the VirusX Documentation|for more information.");
  1085.         return(SimpleRequest(buf, " Will Do. ", Window, SR_ANYKEYQUIT));
  1086.     };
  1087. }
  1088.  
  1089.  
  1090.  
  1091. /**********************************************************************/
  1092. /*          Reads the first 1024 bytes into the 'diskbuffer'          */
  1093. /**********************************************************************/
  1094. int
  1095. ReadBootBlock(void)
  1096. {
  1097.     if (ReadBlock(0, (APTR)diskbuffer) == FALSE) return(FALSE);
  1098.     /* If we got block 0, Block 1 cannot possibly fail. */
  1099.     ReadBlock(1, (APTR)&diskbuffer[512]);
  1100.     return(TRUE);
  1101. }
  1102.  
  1103. /**********************************************************************/
  1104. /*             Read a sector to the given memory location             */
  1105. /**********************************************************************/
  1106. int
  1107. ReadBlock(int block, APTR loc)
  1108. {
  1109.     diskreq->io_Command = CMD_READ;
  1110.     diskreq->io_Data = loc;
  1111.     diskreq->io_Length = 512;
  1112.     diskreq->io_Offset = block*512;
  1113.     DoIO((struct IOStdReq *)diskreq);
  1114.  
  1115.     if (diskreq->io_Error > 0) 
  1116.         return(FALSE);
  1117.  
  1118.     Delay(5);
  1119.     MotorOff();
  1120.  
  1121.     return(TRUE);
  1122. }
  1123.  
  1124. /**********************************************************************/
  1125. /*                     Shove diskbuffer to disk.                      */
  1126. /**********************************************************************/
  1127.  int
  1128. WriteBlock(long block)
  1129. {
  1130.     diskreq->io_Length  = 512;
  1131.     diskreq->io_Data    = (APTR)diskbuffer;
  1132.     diskreq->io_Command = CMD_WRITE;
  1133.     diskreq->io_Offset  = block*512;
  1134.  
  1135.     DoIO(diskreq);
  1136.  
  1137.     if(diskreq->io_Error > 19)
  1138.         return(FALSE);
  1139.  
  1140.     diskreq->io_Command = ETD_UPDATE;
  1141.     DoIO(diskreq);
  1142.  
  1143.     MotorOff();
  1144. }
  1145.  
  1146. /**********************************************************************/
  1147. /*                Return TRUE if disk is not writable.                */
  1148. /**********************************************************************/
  1149. int
  1150. ProtStatus(void)
  1151. {
  1152.     diskreq->io_Flags   = 0;
  1153.     diskreq->io_Command = TD_PROTSTATUS;
  1154.  
  1155.     DoIO(diskreq);
  1156.  
  1157.     if(diskreq->io_Error == TDERR_DiskChanged)
  1158.         return TRUE;
  1159.  
  1160.     if(diskreq->io_Actual)
  1161.         return TRUE;
  1162.  
  1163.     return FALSE;
  1164. }
  1165.  
  1166.  
  1167. /**********************************************************************/
  1168. /*    Look for any virus that might appear other than at boot time    */
  1169. /**********************************************************************/
  1170. void
  1171. CheckMemoryForLinkViruses(void)
  1172. {
  1173. if (CheckRAMForIRQ() == 1)
  1174.         MyRequest("IRQ", 2);
  1175.  
  1176. if (CheckRAMForXeno() == 1)
  1177.     SimpleRequest("A program you ran contained the Xeno virus.|It has been removed from RAM, but VirusX will not|extensively search for it on disk.|Use the KV Utility to check recently executed files.", " Thanks ", Window, SR_ANYKEYQUIT);
  1178.  
  1179. CheckRamForLamer();
  1180. }
  1181.  
  1182.  
  1183. /**********************************************************************/
  1184. /*            Check the disk for any non-bootblock Viruses            */
  1185. /**********************************************************************/
  1186. void
  1187. CheckDriveForLinkViruses(char *drivename)
  1188. {
  1189. int err;
  1190. char buffer[200];
  1191. char dirbuffer[80];
  1192. char filebuffer[100];
  1193. char fnamebuffer[100];
  1194. char ssbuffer[80];
  1195. char sscommand[80];
  1196. char pass;
  1197. BPTR fp = 0;
  1198.  
  1199. /** Check for RLamer Virus **/
  1200. CheckDiskForRLamer(drivename[2]-'0');
  1201.  
  1202. /** GET FIRST COMMAND IN S.S. FOR USE IN CHECKING FOR ANY VIRUS **/
  1203. ssbuffer[0] = 0;
  1204. strcpy(buffer, drivename);
  1205. strcat(buffer, "S/Startup-Sequence");
  1206. fp = Open(buffer, MODE_OLDFILE);
  1207. if (fp != 0) 
  1208.     {
  1209.     /* It's faster to do a single read and find the end of the 
  1210.        string myself, than it is to read the S-S character by character */
  1211.  
  1212.     Read(fp, sscommand, 80);    
  1213.     
  1214.     for (x=0; x<80; x++)
  1215.         {
  1216.         if (sscommand[x] == 32 || sscommand[x] == 10 || sscommand[x] == ';')
  1217.             {
  1218.             sscommand[x] = 0;
  1219.             break;
  1220.             };
  1221.         };
  1222.     }
  1223.  
  1224. Close(fp);
  1225. fp = 0;
  1226.  
  1227. /** Check for BGS9 Virus **/
  1228. strcpy(buffer, drivename);
  1229. strcat(buffer, BGSCheck);
  1230. fp = Lock(buffer, ACCESS_READ);
  1231. if (fp != 0)
  1232.     {
  1233.     BPTR vfp;
  1234.     long VL;
  1235.  
  1236.     vfp = 0;
  1237.  
  1238.     strcpy(buffer, drivename);
  1239.     strcat(buffer, sscommand);
  1240.     vfp = Open(buffer, MODE_OLDFILE);
  1241.     if (vfp == 0)
  1242.         {
  1243.         strcpy(buffer, drivename);
  1244.         strcat(buffer, "C/");
  1245.         strcat(buffer, sscommand);
  1246.         vfp = Open(buffer, MODE_OLDFILE);
  1247.         if (vfp == 0)
  1248.             {
  1249.             strcpy(buffer, "The disk in ");
  1250.             strcat(buffer, drivename);
  1251.             strcat(buffer, "apparently has been|affected by the BGS9 Virus, but|I cannot find the Virus itself.|See the Documentation for more info.");
  1252.             SimpleRequest(buffer, " Okay ", Window, SR_ANYKEYQUIT);
  1253.             goto OuttaHereNow;
  1254.             }
  1255.         };
  1256.  
  1257.     /** Now vfp is the virus's file pointer **/
  1258.     Seek(vfp, 0, OFFSET_END);
  1259.     VL = Seek(vfp, 0, OFFSET_BEGINNING);
  1260.     if (VL != 2608)
  1261.         {
  1262.         char buff[255];
  1263.         strcpy(buff, "A virus that looks like BGS9 was found,|on the file ");
  1264.         strcat(buff, buffer);
  1265.         strcat(buff, ",|but it's Not the BGS9 virus.  You should examine|this file, and the 'Devs' directory on that disk.");
  1266.         SimpleRequest(buff, "Oh No!", Window, 0);
  1267.         } else
  1268.         {
  1269.         char nbuff[80];
  1270.         int err;
  1271.  
  1272.         Close(vfp);
  1273.         vfp = 0;
  1274.         err = DeleteFile(buffer);
  1275.         if (err != 0)
  1276.             {
  1277.             strcpy(nbuff, drivename);
  1278.             strcat(nbuff, BGSCheck);
  1279.             err = Rename(nbuff, buffer);
  1280.             if (err != 0)
  1281.                 {
  1282.                 strcpy(buffer, "BGS9 Virus removed from ");
  1283.                 strcat(buffer, drivename);
  1284.                 SimpleRequest(buffer, "  Thank you  ", Window, 0);
  1285.                 goto OuttaHereNow;
  1286.                 };
  1287.             };
  1288.  
  1289.         strcpy(buffer, "Error removing BGS9 virus from|device ");
  1290.         strcat(buffer, drivename);
  1291.         strcat(buffer, ", file ");
  1292.         strcat(buffer, sscommand);
  1293.         strcat(buffer, ".|Check your startup sequence (the first command in it),|and look in the DEVS directory.");
  1294.         SimpleRequest(buffer, "  Thank you  ", Window, 0);
  1295.         };
  1296.  
  1297.     if (vfp != 0) Close(vfp);
  1298.     };
  1299. OuttaHereNow:
  1300.  
  1301. /** Check for IRQ **/
  1302. pass = 0;
  1303. while (TRUE)
  1304.     {
  1305.     if (pass == 3) break;
  1306.     if (pass > 1 && sscommand[0] == 0) break;
  1307.  
  1308.     switch (pass)
  1309.         {
  1310.         case 0:        /* Check DF0:C/DIR     */
  1311.             strcpy(dirbuffer, drivename);
  1312.             strcat(dirbuffer, "C/");
  1313.             strcpy(filebuffer, "DIR");
  1314.             break;
  1315.         case 1:        /* Check Startup-Sequence */
  1316.             strcpy(dirbuffer, drivename);
  1317.             strcat(dirbuffer, "C/");
  1318.             strcpy(filebuffer, sscommand);
  1319.             break;
  1320.         case 2:        /* Check the drive for the ssname */
  1321.             strcpy(dirbuffer, drivename);
  1322.             strcpy(filebuffer, sscommand);
  1323.             break;
  1324.         };
  1325.  
  1326.     pass++;
  1327.  
  1328.     strcpy(fnamebuffer, dirbuffer);
  1329.     strcat(fnamebuffer, filebuffer);
  1330.  
  1331.     /* if return is 1, we go it. */
  1332.     err = CheckFileForIRQ(fnamebuffer, 0);
  1333.     
  1334.     if (err == 1)
  1335.         {
  1336.         strcpy(buffer, "NOTICE:  The IRQ Virus was found|on the file '");
  1337.         strcat(buffer, fnamebuffer);
  1338.         strcat(buffer, "'.|Okay to remove?");
  1339.  
  1340.         WBenchToFront();
  1341.         err = SimpleRequest(buffer, "Leave it|Remove it", Window, 0);
  1342.         if (err == 0)
  1343.             continue;
  1344.  
  1345.         while (TRUE)
  1346.             {
  1347.             err = CheckFileForIRQ(fnamebuffer, 1);
  1348.             if (err == 1)
  1349.                     {
  1350.                 SetWindowTitles(Window, "Disk Healed.", (STRPTR)-1);
  1351.                 Delay(75);
  1352.                 SetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
  1353.                 break;
  1354.                 } else
  1355.                 {
  1356.                 err = SimpleRequest("Error removing.|Disk may be write protected.|Try Again?", "Cancel|Retry", Window, 0);
  1357.                 if (err == 0) break;
  1358.                 }
  1359.             };
  1360.         };
  1361.     };
  1362. }
  1363.  
  1364.  
  1365. /**********************************************************************/
  1366. /*  Switches between the big, rendered-in window, and the small one.  */
  1367. /**********************************************************************/
  1368. void
  1369. ToggleBigWindow(void)
  1370. {
  1371. if (Window == 0) return;
  1372.  
  1373. VirusesInBigWindow = 0;
  1374.  
  1375. if (WindowBig == FALSE)
  1376.     {
  1377.     /* Make window big: Step 1, Figure Y Height Needed */
  1378.     WindowYDelta = 24;   /* Start at 24: DisksChecked, DisksInstalled */
  1379.     x=0;
  1380.     while (VI[x].Name != 0)
  1381.         {
  1382.         if (VI[x].NumFound != 0)
  1383.             {
  1384.             VirusesInBigWindow++;
  1385.             WindowYDelta += 9;
  1386.             };
  1387.         x++;
  1388.         };
  1389.  
  1390.     if ((Window->TopEdge+Window->Height+WindowYDelta) > Screen->Height)
  1391.         MoveWindow(Window, 0, -Window->TopEdge);
  1392.  
  1393.     SizeWindow(Window, 0, WindowYDelta);
  1394.     WaitForNewSize();
  1395.     WindowBig = TRUE;
  1396.     RenderInfo();
  1397.     }
  1398.     else 
  1399.     {
  1400.     /** Make Window Small **/
  1401.     SizeWindow(Window, 0, -WindowYDelta);
  1402.     WaitForNewSize();
  1403.     WindowYDelta = 0;
  1404.     WindowBig = FALSE;
  1405.     }
  1406. }
  1407.  
  1408.  
  1409. /**********************************************************************/
  1410. /*                       Render the Info Window                       */
  1411. /**********************************************************************/
  1412. int ItemY;
  1413.  
  1414. void
  1415. RenderInfo(void)
  1416. {
  1417. int Num = 0, x = 0, Delta;
  1418. char buff[80];
  1419.  
  1420. while (VI[x].Name != 0)
  1421.     {
  1422.     if (VI[x].NumFound != 0) 
  1423.         Num++;
  1424.     x++;
  1425.     };
  1426.  
  1427. Delta = (Num-VirusesInBigWindow)*9;
  1428. if (Delta != 0)
  1429.     {
  1430.     if ((Window->TopEdge+Window->Height+Delta) > Screen->Height)
  1431.         MoveWindow(Window, 0, -Window->TopEdge);
  1432.     SizeWindow(Window, 0, Delta);
  1433.     WindowYDelta += Delta;
  1434.     WaitForNewSize();
  1435.     };
  1436.  
  1437. VirusesInBigWindow = Num;
  1438.  
  1439. ItemY = 17;
  1440. SetAPen(RP, 1);
  1441. SetDrMd(RP, JAM2);
  1442.  
  1443. RenderItem("Disks Checked:", DisksChecked);
  1444. RenderItem("Disks Installed:", DisksInstalled);
  1445. ItemY += 3;
  1446. x=0;
  1447. while (VI[x].Name != 0)
  1448.     {
  1449.     if (VI[x].NumFound != 0)
  1450.         {
  1451.         strcpy(buff, VI[x].Name);
  1452.         strcat(buff, " Found:");
  1453.         RenderItem(buff, VI[x].NumFound);
  1454.         };
  1455.     x++;
  1456.     };
  1457. }
  1458.  
  1459.  
  1460. /**********************************************************************/
  1461. /*                  Draw an item into the Big Window                  */
  1462. /**********************************************************************/
  1463.  void
  1464. RenderItem(char *Item, int Value)
  1465. {
  1466. char buff[10];
  1467. int Len = strlen(Item);
  1468.  
  1469. SetAPen(RP, 0);
  1470. RectFill(RP, 2, ItemY-7, Window->Width-3, ItemY+2);
  1471. SetAPen(RP, 1);
  1472.  
  1473. Move(RP, 214-(Len*8), ItemY);
  1474. Text(RP, Item, Len);
  1475. Move(RP, 220, ItemY);
  1476. Len = itoa(buff, Value);
  1477. while (strlen(buff) < 6) strcat(buff, " ");
  1478. Text(RP, buff, 5);
  1479. ItemY += 9;
  1480. }
  1481.  
  1482.  
  1483. /**********************************************************************/
  1484. /*                      Convert integer to ASCII                      */
  1485. /**********************************************************************/
  1486.  int
  1487. itoa(char *buff, int value)
  1488. {
  1489. char buf2[11];
  1490. int len = 0;
  1491. int i = 0;
  1492.  
  1493. do    {
  1494.     buf2[len++] = '0'+(value%10);
  1495.     value = value / 10;
  1496.     } while (value > 0);
  1497.  
  1498. len--;
  1499.  
  1500. while (len != -1) 
  1501.     {
  1502.     buff[i++] = buf2[len--];
  1503.     };
  1504.  
  1505. buff[i] = 0;
  1506. return(i);
  1507. }
  1508.  
  1509.  
  1510.  
  1511. /**********************************************************************/
  1512. /*                        Do some IRQ Hunting                         */
  1513. /**********************************************************************/
  1514.  
  1515. #define VTAG     0x00000109L
  1516. #define SLONG    ((long)sizeof(long))
  1517.  
  1518. #define OK        1                     /* no error */
  1519. #define GOTHIM   OK                     /* removed virus from file */
  1520.  
  1521. #define VTAG     0x00000109L            /* virus hunk length */
  1522. #define VSIG1    0x0000FFFEL            /* part of virus signature */
  1523. #define VSIG2    0x61000000L            /* part of virus signature */
  1524.  
  1525.  
  1526. long inp, *buff, size;
  1527.  
  1528. int
  1529. cleanup(int val)
  1530. {
  1531.         if(inp)         Close(inp);
  1532.         if(buff)        FreeMem(buff,size);
  1533.         return val;
  1534. }
  1535.  
  1536. /**********************************************************************/
  1537. /*              Check the passed filename for IRQ Virus.              */
  1538. /*        If flag is FALSE, then just determine, don't remove.        */
  1539. /**********************************************************************/
  1540. int
  1541. CheckFileForIRQ(char *fname, int flag)
  1542. {
  1543.  
  1544.     BPTR flock;
  1545.         int   i = 0;
  1546.         long  nhunk;
  1547.         long tbuff[488/4];
  1548.  
  1549.         buff = 0L;
  1550.  
  1551.     if ((inp = Open(fname, MODE_OLDFILE)) == FALSE)
  1552.         return(FALSE);
  1553.  
  1554.         Read(inp, (char *)&tbuff[0], 487);     /* get the first long word   */
  1555.         if(tbuff[0] != 0x000003F3)            /* check for executable file */
  1556.                 return cleanup(FALSE);
  1557.  
  1558.         if(tbuff[5] != VTAG)
  1559.                 return cleanup(FALSE);
  1560.  
  1561.         Seek(inp,0L,OFFSET_END);               /* seek to end of file         */
  1562.         size = Seek(inp,0L,OFFSET_BEGINNING); /* rewind the file to get size */
  1563.         if(size <= 0L)
  1564.                 return cleanup(FALSE);
  1565.  
  1566.         if((buff = AllocMem(size,0L)) == 0)     /* mem buffer for file */
  1567.                 return cleanup(FALSE);
  1568.  
  1569.         if(Read(inp,(char *)&buff[0],size) != size) /* read entire file into buffer */
  1570.                 return cleanup(FALSE);
  1571.  
  1572.         nhunk = buff[ 2 ];              /* number of hunks in file */
  1573.  
  1574.         while(buff[ i++ ] != 0x000003E9)
  1575.                 ;
  1576.  
  1577.         if( ((buff[ i+1 ] & 0x0000FFFF) != VSIG1)
  1578.       || ((buff[ i+2 ] & 0xFFFF0000) != VSIG2) )
  1579.                 return cleanup(FALSE);
  1580.  
  1581.         if (!flag)
  1582.                 return cleanup(1);
  1583.  
  1584.         Close(inp);
  1585.         if((inp = Open(fname,MODE_NEWFILE)) == 0)
  1586.                 return cleanup(FALSE);
  1587.  
  1588.         buff[2] -= 1;   buff[4] -= 1;   /* readjust program header info */
  1589.  
  1590.         if(Write(inp,(char *)&buff[0],5L*SLONG) != 5L*SLONG)
  1591.                 return cleanup(FALSE);
  1592.  
  1593.         if(Write(inp,(char *)&buff[6],nhunk*SLONG) != nhunk*SLONG)
  1594.                 return cleanup(FALSE);
  1595.  
  1596.         i = i + 8L + VTAG;
  1597.         size = (size/SLONG - i)*SLONG;
  1598.  
  1599.         if(Write(inp,(char *)&buff[i],size) != size)
  1600.                 return cleanup(FALSE);
  1601.  
  1602.         return cleanup(1);
  1603. }
  1604.